/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tencent.tendon.convert.json;

import java.util.*;
import com.tencent.tendon.convert.util.*;
import com.tencent.tendon.convert.json.listeners.*;
import java.lang.reflect.Type;

/**
 *
 * @author nbzhang
 */
@SuppressWarnings("unchecked")
public final class JsonFactory {

	//----------------------------------------------------------------------------------------------------------------------
	private static final HashedMap<Type, JsonListener> listeners = new HashedMap();

	private static final HashedMap<Type, JsonEncoder> encoders = new HashedMap();

	private static final HashedMap<Type, JsonDecoder> decoders = new HashedMap();

	private static final HashedMap<Class, Creator> creators = new HashedMap();

	private static final HashedMap<Class, JsonInterceptor> interceptors = new HashedMap();

	private static final HashedMap<Class, HashMap<String, JsonField>> fields = new HashedMap();

	protected static boolean fieldQutoable = true;

	private JsonFactory() {
	}

	static {

		listeners.put(Boolean.class, JsonBoolListener.getInstance());
		listeners.put(Byte.class, JsonByteListener.getInstance());
		listeners.put(Short.class, JsonShortListener.getInstance());
		listeners.put(Character.class, JsonCharListener.getInstance());
		listeners.put(Integer.class, JsonIntListener.getInstance());
		listeners.put(Float.class, JsonFloatListener.getInstance());
		listeners.put(Long.class, JsonLongListener.getInstance());
		listeners.put(Double.class, JsonDoubleListener.getInstance());

		listeners.put(boolean.class, listeners.get(Boolean.class));
		listeners.put(byte.class, listeners.get(Byte.class));
		listeners.put(short.class, listeners.get(Short.class));
		listeners.put(char.class, listeners.get(Character.class));
		listeners.put(int.class, listeners.get(Integer.class));
		listeners.put(float.class, listeners.get(Float.class));
		listeners.put(long.class, listeners.get(Long.class));
		listeners.put(double.class, listeners.get(Double.class));
		listeners.put(String.class, JsonStringListener.getInstance());

		listeners.put(boolean[].class, JsonBoolArrayListener.getInstance());
		listeners.put(byte[].class, JsonByteArrayListener.getInstance());
		listeners.put(short[].class, JsonShortArrayListener.getInstance());
		listeners.put(char[].class, JsonCharArrayListener.getInstance());
		listeners.put(int[].class, JsonIntArrayListener.getInstance());
		listeners.put(float[].class, JsonFloatArrayListener.getInstance());
		listeners.put(long[].class, JsonLongArrayListener.getInstance());
		listeners.put(double[].class, JsonDoubleArrayListener.getInstance());
		listeners.put(String[].class, JsonStringArrayListener.getInstance());

		creators.put(ArrayList.class, new Creator<ArrayList>() {

			public final ArrayList create(Object... params) {
				return new ArrayList();
			}
		});

		creators.put(HashMap.class, new Creator<HashMap>() {

			public final HashMap create(Object... params) {
				return new HashMap();
			}
		});

		creators.put(HashSet.class, new Creator<HashSet>() {

			public final HashSet create(Object... params) {
				return new HashSet();
			}
		});
	}

	/**
	 * 序列化时字段名是否加上引号， 默认是加上
	 *
	 * @param fieldQutoable0
	 */
	public static void setFieldQutoable(boolean fieldQutoable0) {
		fieldQutoable = fieldQutoable0;
	}

	public static <E> void register(final Class<E> clazz, final JsonInterceptor<? extends E> interceptor) {
		interceptors.put(clazz, interceptor);
	}

	public static <E> void register(final Class clazz, final JsonField field) {
		HashMap<String, JsonField> map = fields.get(clazz);
		if (map == null) {
			map = new HashMap(16);
			fields.put(clazz, map);
		}
		map.put(field.name(), field);
	}

	public static <E> void register(final Class<E> clazz, final JsonListener<E> listener) {
		listeners.put(clazz, listener);
	}

	public static <E> void register(final Class<E> clazz, final Creator<? extends E> creator) {
		creators.put(clazz, creator);
	}

	public static <E> void register(final Type clazz, final JsonEncoder<E> printer) {
		encoders.put(clazz, printer);
	}

	public static <E> void register(final Type clazz, final JsonDecoder<E> decoder) {
		decoders.put(clazz, decoder);
	}

	public static <E> JsonInterceptor<E> findInterceptor(final Class<E> clazz) {
		return interceptors.get(clazz);
	}

	public static JsonField findField(final Class clazz, final String name) {
		HashMap<String, JsonField> map = fields.get(clazz);
		if (map == null) return null;
		return map.get(name);
	}

	public static <E> JsonListener<E> findListener(Type clazz) {
		return listeners.get(clazz);
	}

	public static <E> JsonListener<E> findListener(Class<E> clazz) {
		JsonListener<E> listener = listeners.get(clazz);
		if (listener == null && clazz.isEnum()) {
			listener = new JsonEnumListener((Class<? extends Enum>) clazz);
			listeners.put(clazz, listener);
		}
		return listener;
	}

	public static <E> JsonDecoder<E> findDecoder(final Type clazz) {
		return decoders.get(clazz);
	}

	public static <E> JsonEncoder<E> findEncoder(final Type clazz) {
		return encoders.get(clazz);
	}

	public static <E> JsonEncoder<E> loadEncoder(final Class<E> clazz) {
		JsonEncoder entity = encoders.get(clazz);
		if (entity == null) {
			JsonLoader.loadEncodable(clazz);
			entity = encoders.get(clazz);
		}
		return entity;
	}

	public static <E> JsonDecoder<E> loadDecoder(final Type clazz) {
		JsonDecoder entity = decoders.get(clazz);
		if (entity == null) {
			JsonLoader.loadDecodable(clazz);
			entity = decoders.get(clazz);
		}
		return entity;
	}

	public static <T> Creator<T> findCreator(Class<T> type) {
		return creators.get(type);
	}

	public static <T> Creator<T> loadCreator(Class<T> type) {
		Creator result = creators.get(type);
		if (result == null) {
			result = new DefaultCreator(type);
			creators.put(type, result);
		}
		return result;
	}
}
